package com.cl.it.spider;

import com.access.helper.mbg.entity.*;
import com.access.helper.mbg.service.*;
import com.cl.it.mbg.entity.*;
import com.cl.it.mbg.service.*;
import com.cl.it.utils.DateUtils;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.openqa.selenium.By;
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;

@Component
@Slf4j
public class QccSpider extends AbstractSpider{


    @Autowired
    private IQccCompanyInfoService companyInfoService;

    @Autowired
    private IQccFinancingInfoService financingInfoService;

    @Autowired
    private IQccTenderInfoService tenderInfoService;

    @Autowired
    private IQccJobInfoService jobInfoService;

    @Autowired
    private IQccWenshuInfoService wenshuInfoService;

    @Autowired
    private IQccNoticeInfoService noticeInfoService;

    public QccSpider() {
    }

    public void login(WebDriver driver, WebDriverWait wait) {
        driver.get("https://qcc.com");

        sleep(3000L);

        wait.until(ExpectedConditions.presenceOfElementLocated(By.partialLinkText("登录 | 注册"))).click();

        sleep(1000L);

        driver.findElement(By.linkText("密码登录")).click();

        sleep(1000L);

        driver.findElements(By.cssSelector("input[name='phone-number']")).get(1).sendKeys("17717224389");
        driver.findElement(By.cssSelector("input[name='password']")).sendKeys("kehui.1225");

        driver.findElements(By.cssSelector("button.login-btn")).get(1).click();

        sleep(1000L);
        log.info("step log => 登录成功！");
    }

    public void executeSingleCompany(WebDriver driver, WebDriverWait wait, Company company) {
        sleep(1000L);

        driver.navigate().to(company.getQccUrl());

        sleep(1000L);

        log.info("step log => 跳转公司页 => {}！", company.getQccUrl());

        QccCompanyInfo companyInfo = companyInfo(driver, wait, company, null);
        log.info("step log => 公司信息提取成功 => {}！", company.getName());

        financing(driver, wait, company, companyInfo);
        log.info("step log => 投融资信息提取成功 => {}！", company.getName());

        news(driver, wait, company, companyInfo);
        log.info("step log => 新闻提取成功 => {}！", company.getName());

        tender(driver, wait, company, companyInfo);
        log.info("step log => 招投标信息提取成功 => {}！", company.getName());

        job(driver, wait, company, companyInfo);
        log.info("step log => 招聘信息提取成功 => {}！", company.getName());

        wenshu(driver, wait, company, companyInfo);
        log.info("step log => 判决文书提取成功 => {}！", company.getName());

        notice(driver, wait, company, companyInfo);
        log.info("step log => 开庭公告提取成功 => {}！", company.getName());

        touzi(driver, wait, company, companyInfo);
        log.info("step log => 对外投资提取成功 => {}！", company.getName());

        dynamic(driver, wait, company, companyInfo);
        log.info("step log => 动态提取成功 => {}！", company.getName());

    }

    public QccCompanyInfo companyInfo(WebDriver driver, WebDriverWait wait, Company company, String parentCompanyName) {
        String cominfoTabCssSelector = "section#cominfo table.ntable";

        if (!has(driver, cominfoTabCssSelector)) {
            return null;
        }

        WebElement cominfo = driver.findElement(By.cssSelector("section#cominfo table.ntable"));

        QccCompanyInfo companyInfo = new QccCompanyInfo();
        companyInfo.setName(selectorText(cominfo, "tr:nth-child(1)>:nth-child(4)>div>:nth-child(1)"));
        companyInfo.setCode(selectorText(cominfo, "tr:nth-child(1)>:nth-child(2)>div>:nth-child(1)"));
        companyInfo.setLegalPerson(selectorText(cominfo, "tr:nth-child(2)>:nth-child(2) span.cont>span"));
        companyInfo.setStatus(selectorText(cominfo, "tr:nth-child(2)>:nth-child(4)"));
        companyInfo.setFoundedDate(selectorText(cominfo, "tr:nth-child(2) :nth-child(6)"));
        companyInfo.setRegisteredCapital(selectorText(cominfo, "tr:nth-child(3) :nth-child(2)"));
        companyInfo.setPaidCapital(selectorText(cominfo, "tr:nth-child(3) :nth-child(4)"));
        companyInfo.setRegisteredArea(selectorText(cominfo, "tr:nth-child(6) :nth-child(4)"));
        companyInfo.setEmployeeNum(selectorText(cominfo, "tr:nth-child(7) :nth-child(4) :nth-child(1)"));
        companyInfo.setAddress(selectorText(cominfo, "tr:nth-child(9) :nth-child(2)>div :nth-child(1) :nth-child(1)"));
        companyInfo.setParentCompany(parentCompanyName);

        UpdateWrapper<QccCompanyInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("name", companyInfo.getName());
        updateWrapper.eq("code", companyInfo.getCode());
        companyInfoService.saveOrUpdate(companyInfo, updateWrapper);
        return companyInfo;
    }

    public void financing(WebDriver driver, WebDriverWait wait, Company company, QccCompanyInfo companyInfo) {
        selector(driver, "a[href^='/creport']").click();
        sleep(1000L);
        List<WebElement> financings = selectors(driver, "section#financinginfo .app-ntable>table.ntable>tr");
        if (CollectionUtils.isEmpty(financings)) {
            return;
        }
        for (int i = 1; i < financings.size(); i++) {
            WebElement element = financings.get(i);
            QccFinancingInfo info = new QccFinancingInfo();
            info.setName(companyInfo.getName());
            info.setCode(companyInfo.getCode());
            info.setFinancingDate(selectorText(element, "td:nth-child(2)"));
            info.setProductName(selectorText(element, "td:nth-child(3)"));
            info.setFinancingStage(selectorText(element, "td:nth-child(4)"));
            info.setVoluation(selectorText(element, "td:nth-child(5)"));
            info.setFinancingAmount(selectorText(element, "td:nth-child(6)"));
            info.setMechanisms(selectorText(element, "td:nth-child(7)"));
            String sourceLinkCssSelector = "td:nth-child(8) a";
            info.setSource(has(element, sourceLinkCssSelector) ? selector(element, sourceLinkCssSelector).getAttribute("href") : "");
            info.setSourceFrom(selectorText(element, "td:nth-child(8)"));

            UpdateWrapper<QccFinancingInfo> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("name", info.getName());
            updateWrapper.eq("code", info.getCode());
            updateWrapper.eq("product_name", info.getProductName());
            updateWrapper.eq("financing_stage", info.getFinancingStage());
            updateWrapper.eq("financing_amount", info.getFinancingAmount());
            updateWrapper.eq("mechanisms", info.getMechanisms());
            updateWrapper.eq("financing_date", info.getFinancingDate());
            financingInfoService.saveOrUpdate(info, updateWrapper);
        }
    }

    public void news(WebDriver driver, WebDriverWait wait, Company company, QccCompanyInfo companyInfo) {
        String tabCssSelector = "a[href^='/cnews']";
        if (!has(driver, tabCssSelector)) {
            return;
        }
        selector(driver, tabCssSelector).click();
        sleep(1000L);

        List<WebElement> newsList = selectors(driver, "section#newslist>div.news-list table.ntable tr");
        if (CollectionUtils.isEmpty(newsList)) {
            return;
        }
        for (WebElement element : newsList) {
            News news = new News();
            news.setCode(companyInfo.getCode());
            news.setName(companyInfo.getName());
            news.setTitle(selectorText(element, "div:nth-child(1)>a:nth-child(1)"));
            news.setSource(selectorText(element, "div.relate-info>div:nth-child(2)>span.f:nth-child(2)>span.val"));
            news.setNewsDate(selectorText(element, "div.relate-info>div:nth-child(2)>span.f:nth-child(1)>span.val"));
            news.setTags(selectorText(element, "div:nth-child(1)>div.tags"));
            news.setSourceUrl(selectorText(element, "div:nth-child(1)>a:nth-child(1)"));
            String contentCssSelector = "div:nth-child(1)>div.clampContent";
            news.setContent(has(element, contentCssSelector) ? selectorText(element, contentCssSelector) : "");
            news.setDataSource("企查查新闻");

            UpdateWrapper<News> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("code", news.getCode());
            updateWrapper.eq("name", news.getName());
            updateWrapper.eq("title", news.getTitle());
            updateWrapper.eq("news_date", DateUtils.dateConvert(news.getNewsDate()));

            newsService.saveOrUpdate(news, updateWrapper);
        }
    }

    public void tender(WebDriver driver, WebDriverWait wait, Company company, QccCompanyInfo companyInfo) {
        String tenderTabCssSelector = "a[href^='/crun']";
        if (!has(driver, tenderTabCssSelector)) {
            return;
        }
        selector(driver, "a[href^='/crun']").click();
        sleep(1000L);

        String listCssSelector = "section#tenderlist>div.app-ntable>table.ntable tr";
        String pageCssSelector = "section#tenderlist>div.app-ntable>nav.text-right>ul.pagination";

        new NextPageSpider() {

            @Override
            public int loopStart() {
                return 1;
            }

            @Override
            public Object one(WebElement element) {
                QccTenderInfo info = new QccTenderInfo();
                info.setName(companyInfo.getName());
                info.setCode(companyInfo.getCode());
                info.setProjectName(selectors(element, "td").get(1).getText().trim());
                info.setPublishDate(selectors(element, "td").get(2).getText().trim());
                info.setProvince(selectors(element, "td").get(3).getText().trim());
                info.setTag(selectors(element, "td").get(4).getText().trim());
                info.setTarget(selectors(element, "td").get(5).getText().trim());
                info.setTargetAmount(selectors(element, "td").get(6).getText().trim());
                info.setInfoDetailUrl(selector(element, "td:nth-child(8) a").getAttribute("href"));
                info.setTargetUrl(has(element, "td:nth-child(6) a") ? selector(element, "td:nth-child(6) a").getAttribute("href") : null);

                UpdateWrapper<QccTenderInfo> updateWrapper = new UpdateWrapper<>();
                updateWrapper.eq("code", info.getCode());
                updateWrapper.eq("name", info.getName());
                updateWrapper.eq("project_name", info.getProjectName());
                updateWrapper.eq("publish_date", info.getPublishDate());

                tenderInfoService.saveOrUpdate(info, updateWrapper);
                return info;
            }

            @Override
            public boolean next(SearchContext pagination) {
                if (pagination == null) {
                    return false;
                }
                boolean hasNext = has(pagination, By.linkText(">"));
                if (hasNext) {
                    WebElement nextLink = pagination.findElement(By.linkText(">"));
                    executeScript(driver, "arguments[0].click();", Lists.newArrayList(nextLink));
                }
                return hasNext;
            }
        }.each(driver, listCssSelector, pageCssSelector);
    }

    public void job(WebDriver driver, WebDriverWait wait, Company company, QccCompanyInfo companyInfo) {
        String jobTabCssSelector = "a[href^='/crun']";
        if (!has(driver, jobTabCssSelector)) {
            return;
        }
        selector(driver, jobTabCssSelector).click();
        sleep(1000L);

        String listCssSelector = "section#joblist>div.app-ntable>table.ntable tr";
        String pageCssSelector = "section#joblist>div.app-ntable>nav.text-right>ul.pagination";

        new NextPageSpider() {

            @Override
            public int loopStart() {
                return 1;
            }

            @Override
            public Object one(WebElement element) {
                QccJobInfo info = new QccJobInfo();
                info.setName(companyInfo.getName());
                info.setCode(companyInfo.getCode());
                info.setJobName(selectors(element, "td").get(2).getText().trim());
                info.setPublishDate(selectors(element, "td").get(1).getText().trim());
                info.setSalary(selectors(element, "td").get(3).getText().trim());
                info.setEducation(selectors(element, "td").get(4).getText().trim());
                info.setExperience(selectors(element, "td").get(5).getText().trim());
                info.setAddress(selectors(element, "td").get(6).getText().trim());
                info.setTargetUrl(selector(element, "td:nth-child(8) a").getAttribute("href"));


                UpdateWrapper<QccJobInfo> updateWrapper = new UpdateWrapper<>();
                updateWrapper.eq("code", info.getCode());
                updateWrapper.eq("name", info.getName());
                updateWrapper.eq("job_name", info.getJobName());
                updateWrapper.eq("publish_date", info.getPublishDate());
                updateWrapper.eq("education", info.getEducation());
                updateWrapper.eq("experience", info.getExperience());
                updateWrapper.eq("address", info.getAddress());
                updateWrapper.eq("salary", info.getSalary());

                jobInfoService.saveOrUpdate(info, updateWrapper);
                return info;
            }

            @Override
            public boolean next(SearchContext pagination) {
                if (pagination == null) {
                    return false;
                }
                boolean hasNext = has(pagination, By.linkText(">"));
                if (hasNext) {
                    WebElement nextLink = pagination.findElement(By.linkText(">"));
                    executeScript(driver, "arguments[0].click();", Lists.newArrayList(nextLink));
                }
                return hasNext;
            }
        }.each(driver, listCssSelector, pageCssSelector);
    }

    public void wenshu(WebDriver driver, WebDriverWait wait, Company company, QccCompanyInfo companyInfo) {
        String susongTabCssSelector = "a[href^='/csusong']";
        if (!has(driver, susongTabCssSelector)) {
            return;
        }
        selector(driver, susongTabCssSelector).click();
        sleep(1000L);

        String listCssSelector = "section#wenshulist>div.tablist>div.app-ntable>table.ntable>tr";
        String pageCssSelector = "section#wenshulist>div.tablist>div.app-ntable>nav.text-right>ul.pagination";

        new NextPageSpider() {

            @Override
            public int loopStart() {
                return 1;
            }

            @Override
            public Object one(WebElement element) {
                QccWenshuInfo info = new QccWenshuInfo();
                info.setName(companyInfo.getName());
                info.setCode(companyInfo.getCode());
                info.setTitle(selectors(element, "td").get(1).getText().trim());
                info.setCaseReason(selectors(element, "td").get(2).getText().trim());
                info.setCaseNum(selectors(element, "td").get(3).getText().trim());

                boolean hasMixs = has(selector(element, "td:nth-child(5)"), "div.m-b-xs");
                if (hasMixs) {
                    info.setPlaintiff(selectorText(element, "td:nth-child(5) div.m-b-xs:nth-child(1)"));
                    info.setPlaintiffLawyer(selectorText(element, "td:nth-child(5) div.m-b-xs:nth-child(2)"));
                    info.setDefendant(selectorText(element, "td:nth-child(5) div.m-b-xs:nth-child(3)"));
                    info.setDefendantLawyer(selectorText(element, "td:nth-child(5) div.m-b-xs:nth-child(4)"));
                } else {
                    info.setPlaintiff("-");
                    info.setPlaintiffLawyer("-");
                    info.setDefendant("-");
                    info.setDefendantLawyer("-");
                }

                info.setCaseAmount(selectors(element, "td").get(5).getText().trim());
                info.setCaseResult(selectors(element, "td").get(6).getText().trim());
                info.setPublishDate(selectors(element, "td").get(7).getText().trim());
                info.setRefereeDate(selectors(element, "td").get(8).getText().trim());
                info.setDetailUrl(selectors(element, "td").get(9).getText().trim());

                UpdateWrapper<QccWenshuInfo> updateWrapper = new UpdateWrapper<>();
                updateWrapper.eq("code", info.getCode());
                updateWrapper.eq("name", info.getName());
                updateWrapper.eq("publish_date", info.getPublishDate());
                updateWrapper.eq("title", info.getTitle());
                updateWrapper.eq("case_reason", info.getCaseReason());
                updateWrapper.eq("case_num", info.getCaseNum());

                wenshuInfoService.saveOrUpdate(info, updateWrapper);
                return info;
            }

            @Override
            public boolean next(SearchContext pagination) {
                if (pagination == null) {
                    return false;
                }
                boolean hasNext = has(pagination, By.linkText(">"));
                if (hasNext) {
                    WebElement nextLink = pagination.findElement(By.linkText(">"));
                    executeScript(driver, "arguments[0].click();", Lists.newArrayList(nextLink));
                }
                return hasNext;
            }
        }.each(driver, listCssSelector, pageCssSelector);
    }


    public void notice(WebDriver driver, WebDriverWait wait, Company company, QccCompanyInfo companyInfo) {
        String susongTabCssSelector = "a[href^='/csusong']";
        if (!has(driver, susongTabCssSelector)) {
            return;
        }
        selector(driver, susongTabCssSelector).click();
        sleep(1000L);

        String listCssSelector = "section#noticelist>div.tablist>div.app-ntable>table.ntable>tr";
        String pageCssSelector = "section#noticelist>div.tablist>div.app-ntable>nav.text-right>ul.pagination";

        new NextPageSpider() {
            @Override
            public int loopStart() {
                return 1;
            }

            @Override
            public Object one(WebElement element) {
                QccNoticeInfo info = new QccNoticeInfo();
                info.setName(companyInfo.getName());
                info.setCode(companyInfo.getCode());
                info.setCaseReason(selectors(element, "td").get(3).getText().trim());
                info.setCaseNum(selectors(element, "td").get(1).getText().trim());
                info.setOpenDate(selectors(element, "td").get(2).getText().trim());
                info.setDetailUrl(selectors(element, "td").get(1).findElement(By.cssSelector("a")).getAttribute("href"));
                info.setPlaintiff(selectorText(element, "td:nth-child(5) div:nth-child(1)"));
                info.setDefendant(selectorText(element, "td:nth-child(5) div:nth-child(2)"));

                UpdateWrapper<QccNoticeInfo> updateWrapper = new UpdateWrapper<>();
                updateWrapper.eq("code", info.getCode());
                updateWrapper.eq("name", info.getName());
                updateWrapper.eq("case_reason", info.getCaseReason());
                updateWrapper.eq("case_num", info.getCaseNum());
                updateWrapper.eq("open_date", info.getOpenDate());

                noticeInfoService.saveOrUpdate(info, updateWrapper);
                return info;
            }

            @Override
            public boolean next(SearchContext pagination) {
                if (pagination == null) {
                    return false;
                }
                boolean hasNext = has(pagination, By.linkText(">"));
                if (hasNext) {
                    WebElement nextLink = pagination.findElement(By.linkText(">"));
                    executeScript(driver, "arguments[0].click();", Lists.newArrayList(nextLink));
                }
                return hasNext;
            }
        }.each(driver, listCssSelector, pageCssSelector);
    }

    public void touzi(WebDriver driver, WebDriverWait wait, Company company, QccCompanyInfo companyInfo) {
        String firmTabCssSelector = "a[href^='/firm']";
        if (!has(driver, firmTabCssSelector)) {
            return;
        }
        selector(driver, firmTabCssSelector).click();
        sleep(1000L);

        String listCssSelector = "section#touzilist>div.app-ntable>table.ntable>tr";
        String pageCssSelector = "section#touzilist>div.app-ntable>nav.text-right>ul.pagination";

        List<Object> objs = new NextPageSpider() {
            @Override
            public int loopStart() {
                return 1;
            }

            @Override
            public Object one(WebElement element) {
                String url = selector(selectors(element, "td").get(1), "span.name>a").getAttribute("href");
                return url;
            }

            @Override
            public boolean next(SearchContext pagination) {
                if (pagination == null) {
                    return false;
                }
                boolean hasNext = has(pagination, By.linkText(">"));
                if (hasNext) {
                    WebElement nextLink = pagination.findElement(By.linkText(">"));
                    executeScript(driver, "arguments[0].click();", Lists.newArrayList(nextLink));
                }
                return hasNext;
            }
        }.each(driver, listCssSelector, pageCssSelector);

        if (CollectionUtils.isEmpty(objs)) {
            return;
        }
        SeleniumSpider spider = new SeleniumSpider(chomeDriver);
        for (Object obj : objs) {
            String url = obj.toString();
            spider.getDriver().get(url);
            companyInfo(spider.getDriver(), spider.getWait(), company, companyInfo.getName());
        }
        spider.getDriver().quit();
    }

    public void dynamic(WebDriver driver, WebDriverWait wait, Company company, QccCompanyInfo companyInfo) {
        String url = selector(driver, By.linkText("查看动态")).getAttribute("href");
        driver.navigate().to(url);

        String lookMoreCssSelector = "div.m-t-sm>a.text-primary";
        if (has(driver, lookMoreCssSelector)) {
            List<WebElement> lookMore = selectors(driver, lookMoreCssSelector);
            for (WebElement element : lookMore) {
                element.click();
                sleep(100L);
            }
        }

        String dynamicCssSelector = "div.dynamic-table table.ptable tr";
        if (!has(driver, dynamicCssSelector)) {
            return;
        }
        List<WebElement> dynamics = selectors(driver, dynamicCssSelector);
        for (int i = 0; i < dynamics.size(); i++) {
            WebElement element = dynamics.get(i);
            News news = new News();
            news.setCode(companyInfo.getCode());
            news.setName(companyInfo.getName());
            news.setSource(selectorText(element, "td:nth-child(2)"));
            news.setNewsDate(DateUtils.dateConvert(selectorText(element, "td:nth-child(4)")));
            news.setTags(selectorText(element, "td:nth-child(1)"));
            news.setSourceUrl(href(element, "td:nth-child(3) a"));
            news.setContent(selectorText(element, "td:nth-child(3)"));
            news.setDataSource(selectorText(element, "td:nth-child(2)"));

            UpdateWrapper<News> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("name", companyInfo.getName());
            updateWrapper.eq("code", companyInfo.getCode());
            updateWrapper.eq("content", news.getContent());
            updateWrapper.eq("news_date", news.getNewsDate());
            newsService.saveOrUpdate(news, updateWrapper);
        }
    }
}
